/* Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *      
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License
 */

// we will play this video
var defaultVideoId = 'a7hGiu2hy9k';

// will hold a reference to the player
var player;

// is this is the master instance, will send replies
// to initial sync request
var master = false;

function initYouTube() {
  createYouTubePlayer(defaultVideoId);
}

// add player container to dom and create YT.Player object
function createYouTubePlayer(videoId) {
  $('body').append('<div id="player"></div>');
  player = new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: videoId,
    events: {
      'onReady': onPlayerReady,
    }
  });
}

function onPlayerReady(event) {
  // If I'm the only one in the hangout start reproducing from beginning,
  // otherwise request time sync 
  if (gapi.hangout.getParticipants().length <= 1) {
    player.addEventListener('onStateChange', onPlayerStateChange);
    event.target.playVideo();
    gapi.hangout.data.onStateChanged.add(updateState);
    master = true;
    gapi.hangout.data.setValue('lock', 'free');
  } else {
    gapi.hangout.data.onStateChanged.add(initialSync);
    gapi.hangout.data.setValue('syncRequest', gapi.hangout.getLocalParticipantId().toString());
  }
}

// listener for hangout state changed event when waiting for initial sync
function initialSync(stateChangedEvent) {
  for (var index in stateChangedEvent['addedKeys']) {
    var changedKey = stateChangedEvent['addedKeys'][index]['key'];
    if (changedKey == 'syncReply') {
      var startTime = stateChangedEvent['addedKeys'][index]['value'];
      var playerState = gapi.hangout.data.getValue('playerState');
      player.seekTo(parseInt(startTime));
      if (playerState == 'play') {
        player.playVideo();
      } else if (playerState == 'pause') {
        player.pauseVideo();
      }
      gapi.hangout.data.onStateChanged.remove(initialSync);
      gapi.hangout.data.onStateChanged.add(updateState);
      player.addEventListener('onStateChange', onPlayerStateChange);
    }
  }
}

// listener on youtube player state changes
function onPlayerStateChange(event) {
  var lock = gapi.hangout.data.getValue('lock');
  if (lock == 'free') {
    gapi.hangout.data.setValue('lock', gapi.hangout.getLocalParticipantId());
    // pause could be because of a seekTo action, so we send the new time as well (hacky I know)
    if (event.data == YT.PlayerState.PAUSED) {
      gapi.hangout.data.submitDelta({
        'time': player.getCurrentTime().toString(),
        'playerState': 'pause',
      });
    } else if (event.data == YT.PlayerState.PLAYING) {
      gapi.hangout.data.setValue('playerState', 'play');
    }
    setTimeout(function() {gapi.hangout.data.setValue('lock', 'free');}, 600);
  }
}

// listener on hangout state changed when in time sync with the other instances
function updateState(stateChangedEvent) {
  for (var index in stateChangedEvent['addedKeys']) {
    var changedKey = stateChangedEvent['addedKeys'][index]['key'];
    if (changedKey == 'time') {
      var time = stateChangedEvent['addedKeys'][index]['value'];
      player.seekTo(time);
    } else if (changedKey == 'playerState') {
      var playerState = stateChangedEvent['addedKeys'][index]['value'];
      if (playerState == 'play') {
        player.playVideo();
      } else if (playerState == 'pause') {
        player.pauseVideo();
      }
    } else if (changedKey == 'syncRequest' && isMaster()) {
      gapi.hangout.data.submitDelta({
        'syncReply': player.getCurrentTime().toString(),
        'syncRequest': 'replied'
      });
    }
  }
}

// this should be better and recompute the master anytime there is 
// an initial sync request, because the master could have left the hangout
function isMaster() {
  return master;
}